package com.xiaotu.common.aop;

import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xiaotu.common.exception.SpiderException;
import com.xiaotu.common.exception.SpiderExceptionCode;
import com.xiaotu.common.model.JobLogModel;
import com.xiaotu.common.model.SpiderLogModel;
import com.xiaotu.common.util.Constants;
import com.xiaotu.common.util.FileUtil;
import com.xiaotu.common.util.GsonUtils;
import com.xiaotu.common.util.SepratorUtil;
import com.xiaotu.storage.ACSVStorageProcessor;
import com.xiaotu.storage.JobLogStorageProcessor;
import com.xiaotu.storage.converter.AConverter;
import com.xiaotu.storage.converter.ConverterFactory;
import com.xiaotu.storage.model.CacheDataModel;

import net.sf.json.JSONObject;

/**
 * @类名 StorageProcessLogAspect
 * @日期 2015年5月28日
 * @作者 高海军
 * @功能 针对一条数据转储处理的日志切面
 */
public class StorageProcessLogAspect extends ALogAspect
{
	private static final Logger LOGGER = LoggerFactory
			.getLogger(StorageProcessLogAspect.class);
	
	/**
	 * 对PageProcessor的doProcess方法进行横切，调用方法前后都做相应的异常处理
	 * @param joinPoint 连接点
	 */
	@SuppressWarnings("unchecked")
	public Object aroundMethod(ProceedingJoinPoint joinPoint)
	{
		boolean isLogData = false;
		JobLogModel logModel = new JobLogModel();
		Object result = StringUtils.EMPTY;
		CacheDataModel data = null;
		ACSVStorageProcessor processor = null;
		try
		{
			isLogData = (joinPoint
					.getTarget() instanceof JobLogStorageProcessor);
			
			if (!(joinPoint.getTarget() instanceof ACSVStorageProcessor))
				throw new SpiderException(
						SpiderExceptionCode.StorageProcessorClassErrorException);
			
			processor = (ACSVStorageProcessor) joinPoint.getTarget();
			
			SpiderLogModel taskLog = processor.getTaskLog();// 获取整个任务基本信息
			if (taskLog == null)
				throw new SpiderException(
						SpiderExceptionCode.SpiderTaskInfoErrorException);
			
			logModel.setSeriesNo(taskLog.getSeriesNo());
			logModel.setJobType(processor.getTaskType());
			logModel.setDataType(processor.getDataType());
			
			Object[] args = joinPoint.getArgs();
			if (args == null || args.length < 1
					|| !(args[0] instanceof JSONObject))
				throw new SpiderException(
						SpiderExceptionCode.StorageProcessorParameterErrorException);
			JSONObject target = (JSONObject) args[0];
			data = (CacheDataModel) args[1];
			if (!isLogData)
				setLogInfo(target, logModel, "tvId", "starId");// 记录爬取对象的基本信息
				
			logModel.setTargetContent(target.toString());
			result = joinPoint.proceed();// 处理爬取的数据
			logModel.setJobStatus(Constants.JobStatus.SUCCESS);
		}
		catch (Throwable e)
		{
			if (e instanceof SpiderException)
				logModel.setException(
						((SpiderException) e).getExceptionCode().toString());
			else
				logModel.setException(e.getClass().getSimpleName());
			logModel.setJobStatus(Constants.JobStatus.FAIL);
			logModel.setMessage(e.getMessage());
			
			LOGGER.error("[{}][{}] Storage Processor error {}:",
					logModel.getJobType(), logModel.getDataType(),
					logModel.getException(), e);
		}
		finally
		{
			logModel.setTimestamp(System.currentTimeMillis());
			if (LOGGER.isDebugEnabled())
				LOGGER.debug("[{}][{}] Storage Process Log:",
						logModel.getJobType(), logModel.getDataType(),
						GsonUtils.toJson(logModel));
			if (!isLogData)
				this.saveLog(processor, data, logModel);
		}
		return result;
	}
	
	public static String getLogLine(ACSVStorageProcessor processor,
			JSONObject logModel)
	{
		processor.validateAllNotEmpty(logModel, "seriesNo", "logType",
				"jobType", "targetType", "targetId", "jobStatus");// 校验
		return processor.list2CSVLine(ConverterFactory.convert(logModel,
				new String[] { "seriesNo", "logType", "jobType", "dataType",
						"targetType", "targetId", "targetName", "jobStatus",
						"targetContent", "url", "exception", "message",
						"timestamp" },
				new String[] { AConverter.STRING_CONVERT,
						AConverter.INTEGER_CONVERT, AConverter.STRING_CONVERT,
						AConverter.STRING_CONVERT, AConverter.STRING_CONVERT,
						AConverter.STRING_CONVERT, AConverter.STRING_CONVERT,
						AConverter.STRING_CONVERT, AConverter.STRING_CONVERT,
						AConverter.STRING_CONVERT, AConverter.STRING_CONVERT,
						AConverter.STRING_CONVERT,
						AConverter.TIMESTAMP_CONVERT },
				new boolean[] { true, true, true, true, true, true, true, true,
						true, true, true, true, true }));
	}
	
	private void saveLog(ACSVStorageProcessor processor, CacheDataModel data,
			JobLogModel logModel)
	{
		try
		{
			
			String fileName = data.getFileName() + ".log.csv";
			FileUtil.writeFile(fileName,
					getLogLine(processor, JSONObject.fromObject(logModel))
							+ SepratorUtil.LINE_SEPRATOR);
		}
		catch (Exception e)
		{
			LOGGER.error("[{}][{}] Storage Process Log:", logModel.getJobType(),
					logModel.getDataType(), e);
		}
	}
}
